package com.cswangdao.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.cswangdao.domain.dto.GoodsAddDTO;
import com.cswangdao.domain.dto.GoodsPageDTO;
import com.cswangdao.domain.model.*;
import com.cswangdao.domain.po.Goods;
import com.cswangdao.domain.po.GoodsAttribute;
import com.cswangdao.domain.po.GoodsProduct;
import com.cswangdao.domain.po.GoodsSpecification;
import com.cswangdao.domain.vo.*;
import com.cswangdao.mapper.*;
import com.cswangdao.result.PageResult;
import com.cswangdao.service.GoodsService;
import com.cswangdao.threadlocal.BaseContext;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Service
@Transactional
public class GoodServiceImpl implements GoodsService {

    @Autowired
    private MarketGoodsMapper goodsMapper;

    @Autowired
    private MarketAdMapper adMapper;

    @Autowired
    private MarketCouponMapper couponMapper;

    @Autowired
    private MarketTopicMapper topicMapper;

    @Autowired
    private MarketGoodsAttributeMapper goodsAttributeMapper;

    @Autowired
    private MarketGoodsProductMapper goodsProductMapper;

    @Autowired
    private MarketGoodsSpecificationMapper goodsSpecificationMapper;

    @Autowired
    private MarketCategoryMapper categoryMapper;

    @Autowired
    private MarketBrandMapper brandMapper;

    @Autowired
    private MarketSystemMapper systemMapper;

    @Autowired
    private MarketCouponUserMapper couponUserMapper;


    @Autowired
    private MarketCommentMapper commentMapper;

    @Autowired
    private MarketIssueMapper issueMapper;

    @Autowired
    private MarketCollectMapper collectMapper;


    /**
     * @description: 分页查询商品状态
     * @param: goodsPageDTO
     * @return: com.cswangdao.result.PageResult<com.cswangdao.domain.po.Goods>
     */
    @Override
    public PageResult<Goods> pageQueryInfo(GoodsPageDTO goodsPageDTO) {
        try/*(SqlSession sqlSession = MybatisUtil.getSqlSession(true))*/ {
            PageHelper.startPage(goodsPageDTO.getPage(), goodsPageDTO.getLimit());
            //  MarketGoodsMapper goodsMapper = MapperUtil.getMapper(MarketGoodsMapper.class);
            Page<Goods> page = goodsMapper.pageQueryInfo(goodsPageDTO);
            PageResult<Goods> result = PageResult.result(page);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    /**
     * @description: 新增商品
     * @param: goodsAddDTO
     * @return: boolean
     */
    public boolean insert(GoodsAddDTO goodsAddDTO) {
        try/*( SqlSession sqlSession = MybatisUtil.getSqlSession();) */ {

            //   MarketGoodsMapper goodsMapper = sqlSession.getMapper(MarketGoodsMapper.class);
            Goods goods = goodsAddDTO.getGoods();
            Date now = new Date();
            goods.setUpdateTime(now);
            goods.setAddTime(now);
            BigDecimal minPrice = minPrice(goodsAddDTO.getProducts());
            goods.setRetailPrice(minPrice);
            goodsMapper.insert(goods);
            Integer goodsId = goods.getId();
            //  MarketGoodsAttributeMapper goodsAttributeMapper = sqlSession.getMapper(MarketGoodsAttributeMapper.class);
            List<GoodsAttribute> attributes = goodsAddDTO.getAttributes();
            for (GoodsAttribute attribute : attributes) {
                attribute.setGoodsId(goodsId);
                attribute.setAddTime(now);
                attribute.setUpdateTime(now);
            }
            goodsAttributeMapper.insertBatch(attributes);

            List<GoodsProduct> products = goodsAddDTO.getProducts();
            for (GoodsProduct product : products) {
                product.setGoodsId(goodsId);
                product.setAddTime(now);
                product.setUpdateTime(now);
            }
            // MarketGoodsProductMapper goodsProductMapper = sqlSession.getMapper(MarketGoodsProductMapper.class);
            goodsProductMapper.insertBatch(products);
            //  MarketGoodsSpecificationMapper goodsSpecificationMapper = sqlSession.getMapper(MarketGoodsSpecificationMapper.class);
            List<GoodsSpecification> specifications = goodsAddDTO.getSpecifications();
            for (GoodsSpecification specification : specifications) {
                specification.setGoodsId(goodsId);
                specification.setAddTime(now);
                specification.setUpdateTime(now);
            }
            goodsSpecificationMapper.insertBatch(specifications);
            //  sqlSession.commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean deleteById(Integer goodsId) {
        try {

            goodsMapper.deleteById(goodsId);
            goodsAttributeMapper.deleteByGoodsId(goodsId);
            goodsProductMapper.deletsByGoodsId(goodsId);
            goodsSpecificationMapper.deleteById(goodsId);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public GoodsDetailVo queryById(int goodsId) {

        try {
            MarketGoods goods = goodsMapper.getById(goodsId);
            Integer categoryId = goods.getCategoryId();
            MarketCategory category = categoryMapper.getById(categoryId);
            List<Integer> categoryIds = new ArrayList<>();

            if (category == null) {
                categoryIds.add(0);
                categoryIds.add(0);
            } else {
                categoryIds.add(category.getPid());
                categoryIds.add(categoryId);
            }

            List<MarketGoodsAttribute> goodsAttributes = goodsAttributeMapper.getByGoodsId(goodsId);
            List<MarketGoodsProduct> goodsProducts = goodsProductMapper.getByGoodsId(goodsId);
            List<MarketGoodsSpecification> goodsSpecifications = goodsSpecificationMapper.getByGoodsId(goodsId);
            GoodsDetailVo goodsDetailVo = GoodsDetailVo.builder()
                    .goods(goods)
                    .categoryIds(categoryIds)
                    .attributes(goodsAttributes)
                    .specifications(goodsSpecifications)
                    .products(goodsProducts)
                    .build();
            return goodsDetailVo;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    @Override
    public CatAndBrandVo getCatAndBrandList() {
        try {
            List<MarketBrand> brands = brandMapper.getAll2();
            List<LabelAndValue> brandList = brands.stream().map(new Function<MarketBrand, LabelAndValue>() {
                @Override
                public LabelAndValue apply(MarketBrand marketBrand) {
                    LabelAndValue labelAndValue = new LabelAndValue();
                    labelAndValue.setLabel(marketBrand.getName());
                    labelAndValue.setValue(marketBrand.getId());
                    return labelAndValue;
                }
            }).toList();
            List<LabelAndValue> l1 = categoryMapper.getIdAndName("L1");
            List<LabelAndValue> l2 = categoryMapper.getIdAndName("L2");
            Map<Integer, List<LabelAndValue>> c1 = l2.stream().collect(Collectors.groupingBy(o -> o.getPid()));
            l1.forEach(o -> o.setChildren(c1.get(o.getValue())));
            CatAndBrandVo catAndBrandVo = new CatAndBrandVo();
            catAndBrandVo.setBrandList(brandList);
            catAndBrandVo.setCategoryList(l1);
            return catAndBrandVo;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean update(GoodsAddDTO goodsUpdate) {
        try {
            Goods goods = goodsUpdate.getGoods();
            BigDecimal minPrice = minPrice(goodsUpdate.getProducts());
            goods.setRetailPrice(minPrice);
            goodsMapper.updateById(goods);

            Integer goodsId = goods.getId();
            List<GoodsAttribute> attributes = goodsUpdate.getAttributes();
            for (GoodsAttribute attribute : attributes) {
                goodsAttributeMapper.updateById(attribute);
            }


            List<GoodsProduct> products = goodsUpdate.getProducts();
            for (GoodsProduct product : products) {
                goodsProductMapper.updateById(product);
            }
            List<GoodsSpecification> specifications = goodsUpdate.getSpecifications();
            for (GoodsSpecification specification : specifications) {
                goodsSpecificationMapper.updateById(specification);
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    @Override
    public WXHomeIndexVo index() {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        WXHomeIndexVo wxIndexVo = new WXHomeIndexVo();

        FutureTask<List<MarketAd>> bannerTask = new FutureTask<>(() -> adMapper.getAll());

        FutureTask<List<MarketBrand>> brandListTask = new FutureTask<>(() -> brandMapper.getAll(systemMapper.getValueByName("market_wx_index_brand")));

        FutureTask<List<MarketCategory>> channelTask = new FutureTask<>(() -> categoryMapper.getAll("L1", 5));

        FutureTask<List<FloorGoods>> floorGoodsTask = new FutureTask<>(this::getFloorGoodsList);

        // TODO 用户登录接口完成之后完善
        // HttpServletRequest request = (HttpServletRequest) BaseContext.getHttpServlet().get("request");

        //  Object userId = request.getSession().getAttribute("userId");
        Object userId = null;
        FutureTask<List<MarketCoupon>> couponListTask = null;

        if (Objects.isNull(userId)) {
            couponListTask = new FutureTask<>(() -> couponMapper.getAll(3));
        } else {
            int i = Integer.parseInt(userId.toString());
            //已领取的优惠券
            List<Integer> couponIds = couponUserMapper.getCouponIdsByUserId(i);
            //所有优惠券
            List<Integer> allCouponIds = couponMapper.getAllCouponIds();
            //未领取的优惠券
            allCouponIds.removeAll(couponIds);

            couponListTask = new FutureTask<>(() -> couponMapper.getByIds(allCouponIds, 3));
        }
        FutureTask<List<MarketGoods>> hotGoodsListTask = new FutureTask<>(() -> goodsMapper.getHotOrNewGoods("is_hot", 1, systemMapper.getValueByName("market_wx_index_hot")));

        FutureTask<List<MarketGoods>> newGoodsListTask = new FutureTask<>(() -> goodsMapper.getHotOrNewGoods("is_new", 1, systemMapper.getValueByName("market_wx_index_new")));

        FutureTask<List<MarketTopic>> topicListTask = new FutureTask<>(() -> topicMapper.getAll(systemMapper.getValueByName("market_wx_index_topic")));


        executor.submit(bannerTask);
        executor.submit(brandListTask);
        executor.submit(channelTask);
        executor.submit(floorGoodsTask);
        executor.submit(couponListTask);
        executor.submit(hotGoodsListTask);
        executor.submit(newGoodsListTask);
        executor.submit(topicListTask);

        try {
            wxIndexVo.setChannel(channelTask.get());
            wxIndexVo.setBrandList(brandListTask.get());
            wxIndexVo.setFloorGoodsList(floorGoodsTask.get());
            wxIndexVo.setCouponList(couponListTask.get());
            wxIndexVo.setHotGoodsList(hotGoodsListTask.get());
            wxIndexVo.setNewGoodsList(newGoodsListTask.get());
            wxIndexVo.setTopicList(topicListTask.get());
            wxIndexVo.setBanner(bannerTask.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

        return wxIndexVo;
    }


    //查询目录的下的商品
    private List<FloorGoods> getFloorGoodsList() {
        List<FloorGoods> categoryWithGoods = categoryMapper.getCategoryWithGoods(systemMapper.getValueByName("market_wx_catlog_list"));
        Integer i = systemMapper.getValueByName("market_wx_catlog_goods");
        for (FloorGoods categoryWithGood : categoryWithGoods) {
            List<GoodsOfCategoryVo> goodsList = categoryWithGood.getGoodsList();
            if (Objects.isNull(goodsList) || goodsList.size() <= i) {
                continue;
            }
            List<GoodsOfCategoryVo> goodsOfCategoryVos = goodsList.subList(0, i);
            categoryWithGood.setGoodsList(goodsOfCategoryVos);
        }
        return categoryWithGoods;
    }

    @Override
    public WXGoodsDetailVo getWxGoodsDetail(Integer goodsId) {
        WXGoodsDetailVo wxGoodsDetailVo = new WXGoodsDetailVo();
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        MarketGoods info = goodsMapper.getById(goodsId);

        FutureTask<MarketBrand> brand = new FutureTask<>(() -> brandMapper.getById(info.getBrandId()));
        FutureTask<List<MarketGoodsAttribute>> attribute = new FutureTask<>(() -> goodsAttributeMapper.getByGoodsId(goodsId));
        FutureTask<List<MarketIssue>> issue = new FutureTask<>(() -> issueMapper.getAllIssue());
        FutureTask<List<MarketGoodsProduct>> productList = new FutureTask<>(() -> goodsProductMapper.getByGoodsId(goodsId));
        FutureTask<List<MarketComment>> comment = new FutureTask<>(() -> commentMapper.getByGoodsId(goodsId));
        FutureTask<List<MarketGoodsSpecification>> specification = new FutureTask<>(() -> goodsSpecificationMapper.getByGoodsId(goodsId));
        FutureTask<Boolean> share = new FutureTask<>(() -> Boolean.parseBoolean(systemMapper.getValueIsStringByName("market_wx_share")));


        // TODO 用户登录接口完成之后完善
        FutureTask<MarketCollect> userHasCollext = new FutureTask<>(() -> collectMapper.getByUserIdAndGoodsId(3, goodsId));
        executorService.submit(brand);
        executorService.submit(attribute);
        executorService.submit(issue);
        executorService.submit(productList);
        executorService.submit(comment);
        executorService.submit(specification);
        executorService.submit(share);
        executorService.submit(userHasCollext);

        try {
            wxGoodsDetailVo.setInfo(info);
            wxGoodsDetailVo.setBrand(brand.get());
            wxGoodsDetailVo.setAttribute(attribute.get());
            wxGoodsDetailVo.setIssue(issue.get());
            wxGoodsDetailVo.setProductList(productList.get());
            wxGoodsDetailVo.setShare(share.get());
            wxGoodsDetailVo.setShareImage(info.getShareUrl() == null ? "": info.getShareUrl());
            wxGoodsDetailVo.setComment(new WXCommentVo(comment.get(), comment.get().size()));
            Map<String, List<MarketGoodsSpecification>> collect = specification.get().stream().collect(Collectors.groupingBy(MarketGoodsSpecification::getSpecification));
            List<WXGoodsSpecificationVo> specificationList = new ArrayList<>();
            collect.entrySet().forEach(new Consumer<Map.Entry<String, List<MarketGoodsSpecification>>>() {
                @Override
                public void accept(Map.Entry<String, List<MarketGoodsSpecification>> stringListEntry) {
                    WXGoodsSpecificationVo vo = new WXGoodsSpecificationVo();
                    vo.setName(stringListEntry.getKey());
                    vo.setValueList(stringListEntry.getValue());
                    specificationList.add(vo);
                }
            });
            wxGoodsDetailVo.setSpecificationList(specificationList);
            if (Objects.isNull(userHasCollext.get())) {
                wxGoodsDetailVo.setUserHasCollect(0);
            } else {
                wxGoodsDetailVo.setUserHasCollect(1);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

        return wxGoodsDetailVo;
    }

    @Override
    public PageResult<WXGoodsRelatedVo> getWxGoodsRelated(Integer id) {
        MarketGoods goods = goodsMapper.getById(id);
        Integer brandId = goods.getBrandId();
        // TODO ????
        PageHelper.startPage(1, 6);
        Page<MarketGoods> goodsList = goodsMapper.getGoodsByBrandId(brandId);
        List<WXGoodsRelatedVo> wxGoodsRelatedVos = BeanUtil.copyToList(goodsList, WXGoodsRelatedVo.class);
        return PageResult.builder()
                .limit(6)
                .page(1)
                .pages(goodsList.getPages())
                .list((List) wxGoodsRelatedVos)
                .total(goodsList.getTotal())
                .build();
    }

    //获取商品最低价格
    private BigDecimal minPrice(List<GoodsProduct> products) {
        BigDecimal min = products.stream()
                .map(GoodsProduct::getPrice)
                .min(BigDecimal::compareTo)
                .orElseGet(() -> BigDecimal.ZERO);
        return min;

    }
}
